home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * *** HAPPy Pascal Compiler ***
- * P-code assmebler
- *
- * Copyright (c) H.Asano 1992.
- *
- **********************************************************************/
-
- #define EXTERN extern
- #define Maxlabel 1800 /* 最大ラベル数 */
-
- #include <float.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "version.h"
- #include "hapai.h"
-
- /********* co-operation table **********/
- static unsigned char cop[] =
- {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ 115, 105, 70, 75, 0, 0, 80, 0, 0, 85,
- /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 2x */ 0, 0, 0, 0, 0, 0, 95, 0, 0, 0,
- /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- } ;
-
-
- /***************************************/
- /* P-code 標準手続き・関数ニーモニック表*/
- /***************************************/
- static char sptable[][4] =
- {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ "get","put","rst","rln","new","wln","wrs","wrb","wri","wrr",
- /* 1x */ "wrc","rdi","rdr","rdc","sin","cos","exp","log","sqt","atn",
- /* 2x */ "pge","eof","eol","dis","wrf","rwt","trs","trw","tgt","tpt"
- } ;
-
- /***************************************/
- /* ラベル表 */
- /***************************************/
- enum lbst { entered, /* ラベル未登録の状態 */
- defined /* ラベル定義済の状態 */
- };
-
- static struct {
- int val ; /* value */
- enum lbst st ; /* status {enterd,defined} */
- } labeltab[Maxlabel] ;
-
- /***************************************/
- /* 仮想計算機 記憶装置 */
- /***************************************/
- static _store store[Maxstore] ;
-
- /***************************************/
- /* 変数定義 */
- /***************************************/
- static char *PcodeSourceName; /* P-codeソースファイル名 */
- static char *CompVersion ; /* コンパイラのバージョン */
- static FILE *pcsfile ; /* P-codeソースファイルポインタ */
- static FILE *objfile ; /* P-codeオブジェクトファイルポインタ */
- static int codesize ; /* コードのワードサイズ */
- static int objsize ; /* オブジェクト全体のワードサイズ */
- static int labelvalue ; /* labelの値 */
- static char ch ; /* 読込文字 */
- static int intch ; /* 読込処理内での読込文字 */
- static int pc ; /* program counter */
- static unsigned char op ; /* P-code operation */
- static unsigned char p ; /* P-code p operand */
- static int q ; /* P-code q operand */
- static int start = -1 ; /* オブジェクト開始の合図 */
-
- /*********************************************************************/
-
- /***************************************/
- /* エラーメッセージ出力処理 */
- /***************************************/
- static void paerr(int errno)
- {
- static struct _errmsg {
- int msgno ; /* error message number */
- char *errmsg ; /* error message */
- } errtb[] = {
-
- {1, "命令数が多すぎてアセンブルできない"},
- {2, "オブジェクトファイルがオープンできない"},
- {3, "オブジェクトファイル書き込みでエラーが発生した"},
- {4, "ラベル数が多すぎてアセンブルできない"},
- {5, "定数を格納するメモリを使い果たしてアセンブルできない"},
- {6, "P-codeソースファイルがオープンできない"},
- {7, "PC.EXEとPA.OVLのバージョンが違う"}
- } ;
- int i = -1 ;
-
- while(errtb[++i].msgno != errno) ; /* search message */
- fprintf(stderr,"A%03d: %s\n", errno, errtb[i].errmsg);
- exit(3) ; /* アセンブルエラーで停止 */
- }
-
- /***************************************/
- /* reset() : reset関数 */
- /***************************************/
- static void reset(char *filename)
- {
-
- pcsfile = fopen(filename,"r") ;
- if(pcsfile == NULL) paerr(6) ;
-
- intch = getc(pcsfile) ; /* 1文字先読み */
- }
-
- /***************************************/
- /* eoln() : eolnマクロ定義 */
- /***************************************/
- #define eoln() (intch == '\n') /* 改行を読んでいれば真 */
-
- /***************************************/
- /* readc() : char型read処理 */
- /***************************************/
- static char readc(void)
- {
- int oldch ;
-
- oldch = intch ;
- intch = getc(pcsfile) ;
- return((char)oldch) ;
- }
-
- /***************************************/
- /* readi() : integer型入力処理 */
- /***************************************/
- static integer readi(void)
- {
- integer ival = 0 ;
- int sign = 1 ;
-
- if(intch == ' ')
- while((intch = getc(pcsfile)) == ' '); /* 空白読み飛ばし */
-
- if((intch=='+') || (intch=='-')) { /* 符号の時 */
- sign = (intch=='+') ? 1 : -1 ; /* 符号に応じた正負 */
- intch = getc(pcsfile) ;
- }
-
- do {
- intch -= '0' ;
- ival = ival*10 + intch ;
- if(eoln()) break ; /* EOLNならばそこまで */
- intch=getc(pcsfile) ;
- } while(('0' <= intch) && (intch <= '9')) ;
-
- return(sign*ival) ;
- }
-
- /***************************************/
- /* readr() : real型入力処理 */
- /***************************************/
- static float readr(void)
- {
- char buf[20] ;
- int i = 0 ;
-
- while(intch == ' ') intch = getc(pcsfile) ; /* 空白読み飛ばし */
- do {
- buf[i++] = (char)intch ;
- intch = getc(pcsfile) ;
- } while (intch != '\n') ;
-
- return((float)atof(buf)) ; /* 浮動小数点へ変換 */
- }
-
- /***************************************/
- /* readln() : EOLまで読み飛ばす処理 */
- /***************************************/
- static void readln(void)
- {
- while(!eoln()) intch = getc(pcsfile) ;
- intch = getc(pcsfile);
- }
-
- /***************************************/
- /* オブジェクトファイル書出処理 */
- /***************************************/
- static void putobject(char *area, int size)
- {
- fwrite(area,size,1,objfile) ;
- if(ferror(objfile)) paerr(3) ; /* 書き込み失敗 */
- }
-
- /***************************************/
- /* 初期設定処理 */
- /***************************************/
- static void init(void)
- {
- int i;
-
- _fpreset() ; /* 浮動小数点パッケージ初期設定*/
- for(i=0;i<Maxlabel;i++) { /* ラベル表 の 初期設定 */
- labeltab[i].val = -1 ;
- labeltab[i].st = entered;
- }
-
- reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
-
- objfile = fopen("pcode.pco","wb") ;/* ファイルオープン */
- if(objfile == NULL) paerr(2) ; /* オープンできない */
-
- if(codesize > Maxstore) /* 記憶装置の大きさより大きい時*/
- paerr(1) ; /* プログラム停止 */
-
- if(strcmp(CompVersion,version))
- paerr(7) ; /* バージョン不一致 */
-
- putobject(version,strlen(version)+1) ; /* バージョン番号書出 */
-
- objsize = codesize ;
- }
-
- /***************************************/
- /* ラベル表登録処理 */
- /***************************************/
- static void update(int x)
- { /* x: label名 */
- int curr,succ ;
-
- if(x > Maxlabel-1) paerr(4) ; /* ラベル数が多すぎる */
-
- if(labeltab[x].val != -1) { /* 前方参照されている時 */
- curr = labeltab[x].val;
- for(;;) {
- succ = store[curr].vo.cdq;
- store[curr].vo.cdq = labelvalue;
- if(succ == -1) break; /* 終了 */
- else curr = succ;
- }
- }
- labeltab[x].st = defined ;
- labeltab[x].val = labelvalue ;
- }
-
- /***************************************/
- /* ラベル値決定処理 */
- /***************************************/
- static void lookup(int x)
- {
- if(labeltab[x].st == entered) { /* 未定義 */
- q = labeltab[x].val ; /* 初期値のまま -1 */
- labeltab[x].val = pc ; /* 今のpcを格納 */
- }
- else q = labeltab[x].val ; /* 定義済の時 */
- }
-
- /***************************************/
- /* ラベル値読込処理 */
- /***************************************/
- static void labelsearch(void)
- {
- while(ch != 'L') /* 'L' まで 読み飛ばし */
- ch = readc() ;
- lookup((int)readi()); /* labelを読み 値を探す */
- }
-
-
- /********* typesymbol() : instruction名4文字目によってopを決定する *********/
- static void typesymbol(void)
- {
- int i;
-
- switch(ch) {
- case 'i' : return ; /* 'i' の時は opはそのまま */
- case 'a' : i=0; break;
- case 'r' : i=1; break;
- case 's' : i=2; break;
- case 'b' : i=3; break;
- case 'c' : i=4;
- }
- op=cop[op]+i; /* opの変更 */
- }
-
- /**************************************/
- /* PTN0() : オペランドのない命令 */
- /**************************************/
- static void PTN0(void)
- {
- }
-
- /**************************************/
- /* PTN1() : lod,strのアセンブル */
- /**************************************/
- static void PTN1(void)
- {
- typesymbol() ;
- p=(unsigned char)readi() ;
- q=(int)readi() ;
- }
-
- /**************************************/
- /* PTN2() : lda,movのアセンブル */
- /**************************************/
- static void PTN2(void)
- {
- p=(unsigned char)readi() ;
- q=(int)readi() ;
- }
-
- /***************************************/
- /* PTN3() : mst,cui,bas,traのアセンブル*/
- /***************************************/
- static void PTN3(void)
- {
- p=(unsigned char)readi() ;
- }
-
- /**************************************/
- /* PTN4() : cup,ent,ejpのアセンブル */
- /**************************************/
- static void PTN4(void)
- {
- p=(unsigned char)readi() ;
- labelsearch();
- }
-
- /************************************************/
- /* PTN5() : equ,neq,geq,grt,leq,lesのアセンブル */
- /************************************************/
- static void PTN5(void)
- {
- switch(ch) {
- case 'a' : ; break ;
- case 'i' : p=1 ; break ;
- case 'r' : p=2 ; break ;
- case 'b' : p=3 ; break ;
- case 's' : p=4 ; break ;
- case 'c' : p=6 ; break ;
- case 'm' : p=5 ;
- q=(int)readi() ;
- }
- }
-
- /**************************************/
- /* PTN6() : ldo,sroのアセンブル */
- /**************************************/
- static void PTN6(void)
- {
- typesymbol() ;
- q=(int)readi();
- }
-
- /**************************************/
- /* PTN7() : inc,decのアセンブル */
- /**************************************/
- static void PTN7(void)
- {
- switch(ch) {
- case 'a' :/*p=0*;*/ break ;
- case 'i' : p=1; break ;
- case 'r' : p=2; break ;
- case 'b' : p=3; break ;
- case 'c' : p=6; break ;
- }
- q = (int)readi() ;
- }
-
- /****************************************/
- /* PTN8() : ujp,fjp,xjp,lapのアセンブル */
- /****************************************/
- static void PTN8(void)
- {
- labelsearch() ;
- }
-
- /**************************************/
- /* CHK() : chkのアセンブル */
- /**************************************/
- static void CHK(void)
- {
- integer lb,ub ;
-
- typesymbol() ;
- p = (unsigned char)readi() ; /* チェック種別 */
- lb = readi(); /* 下限値 */
- ub = readi(); /* 上限値 */
- store[objsize ].vi = lb ;
- store[objsize+1].vi = ub ;
- q=codesize;
- do {
- q++ ;
- } while((store[q-1].vi != lb) || (store[q].vi != ub)) ;
- if(q-1 == objsize) {
- objsize += 2 ;
- if(objsize>=Maxstore) paerr(5) ; /* 定数格納不可 */
- }
- }
-
- /**************************************/
- /* CSP() : cspのアセンブル */
- /**************************************/
- static void CSP(void)
- {
- char name[4];
-
- do ;
- while((ch=readc())==' ') ; /* 空白を読み飛ばし */
- *name = ch ; /* 1文字目 */
- *(name+1) = readc() ; /* 2文字目 */
- *(name+2) = readc() ; /* 3文字目 */
- *(name+3) = '\0' ;
- while(strcmp(sptable[q],name) != 0)/*対応のqをサーチ */
- q++ ;
- }
-
- /**************************************/
- /* IND() : indのアセンブル */
- /**************************************/
- static void IND(void)
- {
- typesymbol() ;
- q=(int)readi() ;
- }
-
- /**************************************/
- /* IXA() : ixaのアセンブル */
- /**************************************/
- static void IXA(void)
- {
- integer lb,ub ;
-
- lb = readi() ; /* 下限値 */
- ub = readi() ; /* ixa値 */
- store[objsize ].vi = lb ;
- store[objsize+1].vi = ub ;
- q=codesize;
- do {
- q++ ;
- } while((store[q-1].vi != lb) || (store[q].vi != ub)) ;
- if(q-1 == objsize) {
- objsize += 2 ;
- if(objsize>=Maxstore) paerr(5) ; /* 定数域格納不可 */
- }
- }
-
- /**************************************/
- /* LAO() : laoのアセンブル */
- /**************************************/
- static void LAO(void)
- {
- q=(int)readi();
- }
-
- /**************************************/
- /* LCA() : lcaのアセンブル */
- /**************************************/
- static void LCA(void)
- {
- q=objsize;
- readc() ; /* "を読み飛ばす */
- ch=readc() ; /* "の次の文字 */
- while(ch != '\"') {
- store[objsize++].vc = ch ;
- if(objsize>=Maxstore)
- paerr(5) ; /* 定数格納不可 */
- ch=readc() ; /* 次の文字 */
- }
- }
-
- /**************************************/
- /* LDC() : ldcのアセンブル */
- /**************************************/
- static void LDC(void)
- {
- integer lnumber ;
- float rnumber ;
- long s,s1 ;
-
- switch(ch) {
- case 'i' : p=1 ; /* integer type */
- lnumber = readi() ;
- if(labs(lnumber) < (long)Largeint)
- q = (int)lnumber;
- else { /* 大きな数の時 */
- op = 66 ; /* lci命令に変更 */
- store[objsize].vi = lnumber ;
- q=codesize-1;
- do ;
- while(store[++q].vi != lnumber) ;
- if(q == objsize) {
- objsize++ ;
- if(objsize>=Maxstore)
- paerr(5) ; /* 定数格納不可 */
- }
- }
- break ;
-
- case 'c' : p=6 ; /* char type */
- while((ch=readc())==' ') ;
- q=readc() ;
- break ;
-
- case 'b' : p=3; /* boolean */
- q=(int)readi() ;
- break;
-
- case 'n' : p=0 ; /* ldc nil */
- q=0 ;
- break ;
-
- case 's' : p = 4; /* set type */
- s=0;
- while(readc() != '(') ;
- ch=readc() ;
- while(ch!=')') {
- s1=(int)readi() ;
- addset(s,s1) ;
- ch=readc() ;
- }
- store[objsize].vs = s ;
- q = codesize ;
- while(store[q].vs != s) q++ ;
- if(q==objsize) {
- objsize++ ;
- if(objsize>=Maxstore)
- paerr(5) ; /* 定数格納不可 */
- }
- break ;
-
- case 'r' : p = 2 ;
- rnumber = readr() ;
- store[objsize].vr = rnumber ;
- lnumber = store[objsize].vi ;
- /* 浮動小数点の形で比較を行うと思わぬ落とし穴があるので
- ビット列の比較をするために、union型のviから数を得る*/
- q=codesize-1;
- do ;
- while(store[++q].vi != lnumber) ;
- if(q == objsize) {
- objsize++ ;
- if(objsize>=Maxstore)
- paerr(5) ; /* 定数格納不可 */
- }
- break ;
- }
- }
-
- /**************************************/
- /* ORD() : ordのアセンブル */
- /**************************************/
- static void ORD(void)
- {
- switch(ch) {
- case 'b' : p=3 ; break ;
- case 'c' : p=6 ;
- }
- }
-
- /**************************************/
- /* RET() : retのアセンブル */
- /**************************************/
- static void RET(void)
- {
- switch(ch) {
- case 'p' : ; break ;
- case 'i' : p=1 ; break ;
- case 'r' : p=2 ; break ;
- case 'c' : p=3 ; break ;
- case 'b' : p=4 ; break ;
- case 'a' : p=5 ; break ;
- }
- }
-
- /**************************************/
- /* STO() : stoのアセンブル */
- /**************************************/
- static void STO(void)
- {
- typesymbol() ;
- }
-
- /**********************************************************************/
- /* P-code ニーモニック表 */
- /**********************************************************************/
- static char instr[][4] =
- {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ "lod","ldo","str","sro","lda","lao","sto","ldc","bas","ind",
- /* 1x */ "inc","mst","cup","ent","ret","csp","ixa","equ","neq","geq",
- /* 2x */ "grt","leq","les","ujp","fjp","xjp","chk","lap","adi","adr",
- /* 3x */ "sbi","sbr","sgs","flt","flo","trc","ngi","ngr","sqi","sqr",
- /* 4x */ "abi","abr","not","and","ior","dif","int","uni","inn","mod",
- /* 5x */ "odd","mpi","mpr","dvi","dvr","mov","lca","dec","stp","ord",
- /* 6x */ "chr","ujc","mms","msi","cui","ejp","...","cka","tra","rou"
- } ; /* ↑ ここはlci */
-
- /******* ニーモニック対応のエントリ表 ********/
- static struct entry {
- void (*func)(void) ;
- } OP[] = {
- /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 */
- /* 0x */ PTN1, PTN6 ,PTN2, PTN6, PTN2, LAO , STO , LDC , PTN3, IND ,
- /* 1x */ PTN7, PTN3, PTN4, PTN4, RET , CSP , IXA , PTN5, PTN5, PTN5,
- /* 2x */ PTN5, PTN5, PTN5, PTN8, PTN8, PTN8, CHK , PTN8, PTN0, PTN0,
- /* 3x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
- /* 4x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0, PTN0,
- /* 5x */ PTN0, PTN0, PTN0, PTN0, PTN0, PTN2, LCA , PTN7, PTN0, ORD ,
- /* 6x */ PTN0, PTN0, PTN0, PTN0, PTN3, PTN4, PTN0, PTN0, PTN3, PTN0
- } ;
-
- /***************************************/
- /* 1行アセンブル処理 */
- /***************************************/
- static void assemble(void)
- {
- char name[4];
-
- *name = ch ; /* 1文字目 */
- *(name+1) = readc() ; /* 2文字目 */
- *(name+2) = readc() ; /* 3文字目 */
- *(name+3) = '\0' ;
- if(!eoln()) ch=readc();
- /* そこで行が終わってなければ次の文字を読む */
-
- op = -1 ;
- while(strcmp(instr[++op],name)) ; /* instructionよりopを決定 */
- /* このようなリニアサーチはスピードが遅いので改良しよう */
-
- p = 0 ;
- q = 0 ;
- OP[op].func() ; /* opに対応したアセンブル */
-
- store[pc ].vo.cdop = op; /* code table へ 格納 */
- store[pc ].vo.cdp = p ;
- store[pc++].vo.cdq = q ;
- }
-
- /********** generate() : 行の最初に呼ばれる処理 **********/
- static void generate(void)
- {
- int x ; /* label値 */
- int i ; /* 作業カウンタ */
- char progname[33] ; /* プログラム名 */
- char filename[33] ; /* ファイル名 */
- int fileadr ; /* ファイルアトレス */
- int filesize ; /* バッファ変数の大きさ */
-
- for(;;) {
- ch=readc(); /* 行の最初の文字を読む */
- switch(ch) {
- case 'Q' : return ; /* アセンブル終わり */
-
- case 'N' : /* プログラム名 */
- readc() ; /* 空白を読み飛ばす */
- i=0 ;
- while(!eoln()) /* プログラム名取得 */
- progname[i++] = readc() ;
- progname[i] = '\0' ;
- putobject(progname,i+1) ; /* 書出 */
- break ;
-
- case 'F' : /* ファイルアドレス */
- readc() ; /* 空白を読み飛ばす */
- i=0 ;
- while((ch=readc()) != ' ') /* ファイル名取得 */
- filename[i++] = ch ;
- filename[i] = '\0' ;
- readc() ; /* 空白を読み飛ばす*/
- fileadr = (int)readi() ; /* ファイルアトレス */
- putobject((char*)&fileadr,sizeof(fileadr));/* 書出 */
- filesize = (int)readi(); /* バッファサイズ */
- putobject((char*)&filesize,sizeof(filesize));/* 書出*/
- putobject(filename,i+1) ; /* ファイル名書出 */
- break ;
-
- case ';' : /* 注釈行を無視 */
- break ;
- case 'L' : x=(int)readi(); /* label名を読む */
- if(!eoln()) ch=readc() ;
- if(ch=='=') labelvalue=(int)readi();
- /* label値がある時 */
- else labelvalue=pc; /* ない時はpcの値 */
- update(x); /* label登録 */
- break ;
- case ' ' : ch=readc(); /* 空白の時は その行をアセンブル */
- assemble();
- default : ;
- }
- readln() ;
- }
- }
-
- /*****************************************/
- /* assemblelist() : アセンブルリスト出力 */
- /*****************************************/
- static void assemblelist(void)
- {
- reset(PcodeSourceName) ; /* P-codeソースファイルのオープン */
-
- printf("\n ADDR OP P Q P-code source statement\n");
- printf( "================================================\n");
-
- pc = 0 ;
-
- for(;;) {
- ch=readc(); /* 行の最初の文字 */
- switch(ch) {
- case 'N' :
- case 'F' :
- case 'Q' :
- case ';' :
- case 'L' : printf(" %c",ch);
- while(!eoln()) printf("%c",readc());
- printf("\n");
- readln();
- if(ch=='Q') {
- if(codesize != objsize)
- printf(" %4d:\n ~: constant data\n %4d:\n",
- codesize,objsize-1) ;
- fclose(pcsfile) ; /* ソースファイルのクローズ */
- return;
- }
- break;
-
- case ' ' : printf(" %4d: %3d %3d %6d",
- pc, store[pc].vo.cdop, store[pc].vo.cdp ,
- store[pc].vo.cdq);
- pc++;
- printf(" %c",ch);
- while(!eoln()) printf("%c",readc());
- printf("\n");
- readln();
- break;
- }
- }
- }
-
- /***************************************/
- /* main() : P-codeアセンブラメイン処理 */
- /***************************************/
- int main(int argc,char *argv[])
- {
- codesize = atoi(argv[1]) ; /* 命令コードの数 */
- PcodeSourceName = argv[2] ; /* P-codeソースファイル名 */
- CompVersion = argv[3] ; /* コンパイラのバージョン */
- init(); /* 各種初期設定 */
- generate(); /* アセンブル */
- fclose(pcsfile) ; /* ソースファイルのクローズ */
-
- for(pc=0;pc<codesize;pc++) { /* qオペランドの補正処理 */
- op = store[pc].vo.cdop ;
- if((/*lao*/ op == 5) || (/*ldox*/ op == 1 || (105<=op && op<=109) )
- || (/*srox*/ op == 3 || (75<=op && op<=79) ) )
- store[pc].vo.cdq += objsize ;
- }
-
- putobject((char*)&start,sizeof(start)) ; /* オブジェクト開始合図 */
- putobject((char*)store,objsize*sizeof(_store)) ; /* オブジェクト出力*/
- if(fflush(objfile) == EOF) paerr(3) ;
- if(fclose(objfile) == EOF) paerr(3) ;
- /* クローズできなければ書き込み失敗の可能性がある */
-
- fputs( " *** Assemble completed. ***\n",stderr);
- fprintf(stderr," *** code = %5d words constant data = %5d words ***\n",
- codesize, objsize-codesize);
-
- if(argc==5) assemblelist(); /* アセンブルリストの出力 */
-
- return(0) ; /* 正常終了 */
- }